package com.adv.ems.utils;

import cn.hutool.json.JSONUtil;
import com.adv.ems.db.entity.UserDO;
import com.adv.ems.model.dto.BusinessException;
import com.adv.ems.model.dto.LoginInfo;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class JwtUtil {
    public static ThreadLocal<LoginInfo> threadLocal = new ThreadLocal<>();
    private final static String SECRET = "123456789";

    public static String createToken(UserDO user) {
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setId(user.getId());
        loginInfo.setLoginTime(new Date().getTime());
        loginInfo.setUsername(user.getUserName());
        loginInfo.setRoles(user.getRole());

        Map<String, Object> header = new HashMap<>();
        Map<String, Object> paylad = new HashMap<>();
        JSONUtil.toBean(JSONUtil.toJsonStr(loginInfo), Map.class).forEach((k, v) -> {
            paylad.put(k.toString(), v);
        });
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 1);
        return JWT
                .create()
                .withHeader(header)
                .withExpiresAt(calendar.getTime())
                .withPayload(paylad)
                .sign(Algorithm.HMAC384(SECRET));
    }

    public static LoginInfo getLoginUser() {
        LoginInfo loginVO = threadLocal.get();
        if (loginVO == null) {
            throw new BusinessException(501, "请登录");
        }
        return loginVO;
    }

    public static LoginInfo verifyToken(String token) {
        try {
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC384(SECRET)).build();
            DecodedJWT verify = jwtVerifier.verify(token);
            Map<String, Claim> claims = verify.getClaims();
            LoginInfo loginVO = new LoginInfo();
            loginVO.setLoginTime(claims.get("loginTime").asLong());
            loginVO.setUsername(claims.get("username").asString());
            loginVO.setId(claims.get("id").asLong());
            return loginVO;
        } catch (SignatureVerificationException ex) {
            log.warn("SignatureVerificationException {}", token, ex);
            throw new RuntimeException("无效的签名");
        } catch (TokenExpiredException ex) {
            log.warn("TokenExpiredException {}", token, ex);
            throw new RuntimeException("token过期");
        } catch (AlgorithmMismatchException ex) {
            log.warn("AlgorithmMismatchException {}", token, ex);
            throw new RuntimeException("签名算法验证失败");
        }catch (Exception ex) {
            log.warn("Invalid JWT signature {}", token, ex);
            throw new RuntimeException("token验证异常");
        }
    }
}
